
import { MessageEventMap, PointerEventInfo, SettingState, Settings, WheelEventInfo, } from './types.ts';
import { InitEvent, SettingEvent, UIStateEvent } from './events.ts';
import { STATE } from './handlers/oribits/OrbitControls.ts'
import { UIState, dom2GLPosition } from './states/ui.ts';
import { Renderer } from './states/renderer.ts';
import { ResizeHandler } from './handlers/resize.ts';
import { PickupHandler } from './handlers/pickup.ts';
import { OrbitHandler } from './handlers/oribits/index.ts';
import { SettingHandler } from './handlers/setting/handler.ts';
let renderer: Renderer,
  stateMgr: StateManager
/**
 * 状态管理器,处理逻辑主要是将dom坐标转化为webgl坐标系
 */
class StateManager extends UIState {

  resize(width: number, height: number) {
    this.width = width
    this.height = height
    this.dispatchEvent(new UIStateEvent(renderer, this))
  }
  wheel(e: WheelEventInfo) {
    this.eventType = e.type
    this.wheelEventDeltaY = e.deltaY
    this.whellEventModel = e.deltaMode

    this.dispatchEvent(new UIStateEvent(renderer, this))
  }
  mouseDown(e: PointerEventInfo) {
    this.eventType = e.type
    this.pointerType = e.pointerType
    this.pointerDownButton = e.button
    this.downdOriginalXOY.set(e.offsetX, -e.offsetY)
    Object.assign(this.downNormalizedXOY, dom2GLPosition(e, this.width, this.height))
    this.dispatchEvent(new UIStateEvent(renderer, this))
  }
  mouseMove(e: PointerEventInfo) {
    this.eventType = e.type
    this.pointerType = e.pointerType
    this.currentOriginalXOY.set(e.offsetX, -e.offsetY)
    Object.assign(this.currentNormalizedXOY, dom2GLPosition(e, this.width, this.height))
    this.dispatchEvent(new UIStateEvent(renderer, this))
  }
  mouseUp(e: PointerEventInfo) {

    this.eventType = e.type
    this.pointerType = e.pointerType
    Object.assign(this.upNormalizedXOY, dom2GLPosition(e, this.width, this.height))
    this.upOringinalXOY.set(e.offsetX, -e.offsetY)
    this.pointerDownButton = STATE.NONE;
    this.dispatchEvent(new UIStateEvent(renderer, this))
  }


  keyboardDown(t: MessageEventMap['keyboard']) {
    const sise = this.keyDownCode.size;
    this.keyDownCode.add(t.code);
    this.ctrlKey = t.ctrlKey
    this.shiftKey = t.shiftKey
    this.altKey = t.altKey
    this.metaKey = t.metaKey
    // 已有的按键和早已有的按键
    if (sise !== this.keyDownCode.size) {
      this.dispatchEvent(new UIStateEvent(renderer, this))
    }
  }
  keyboardUp(t: MessageEventMap['keyboard']) {
    this.keyDownCode.delete(t.code);
    this.ctrlKey = false
    this.shiftKey = false
    this.altKey = false
    this.metaKey = false


  }
  setting = (setting: SettingState) => {
    this.dispatchEvent(new SettingEvent(renderer, setting))
  }
}






export type EventReceiver<T extends MessageEventMap = MessageEventMap> = {
  [prop in keyof T]: (p: T[prop]) => void
}

/**
 * 事件接收器
 * 接收来自主线程的消息并分发给渲染器
 * 用于分发自定义事件,在有需要的地方接受自定义事件
 */
const receiver: EventReceiver = {
  init(t: MessageEventMap['init']) {
    stateMgr = new StateManager();
    const setting = new Settings()
    renderer = new Renderer(t.canvas, t.setting || setting);

    stateMgr.dispatchEvent(new InitEvent(renderer, stateMgr));

    const settingHandler = new SettingHandler(t.setting || setting);
    const pickupHandler = new PickupHandler();
    const orbitHandler = new OrbitHandler(renderer.camera, t.canvas.width, t.canvas.height);
    const resizeHandler = new ResizeHandler();
    stateMgr.addEventListener('setting', settingHandler.handler);
    stateMgr.addEventListener('ui', resizeHandler.handler);
    stateMgr.addEventListener('ui', orbitHandler.handler);
    stateMgr.addEventListener('ui', pickupHandler.handler);
  },
  setting(t: MessageEventMap['setting']) {

    stateMgr.setting(t);
  },
  resize(t: MessageEventMap['resize']) {
    stateMgr.resize(t.width, t.height);
  },
  keyboard(t: MessageEventMap['keyboard']) {
    switch (t.type) {
      case 'keydown':
        stateMgr.keyboardDown(t);
        break;
      case 'keyup':
        stateMgr.keyboardUp(t);
        break;
    }
  },

  pointer(p: PointerEventInfo) {
    switch (p.type) {
      case 'pointerdown':
        stateMgr.mouseDown(p);
        break;

      case 'pointermove':
        stateMgr.mouseMove(p);
        break;
      case 'pointerup':
        stateMgr.mouseUp(p)
        break;

      case 'pointercancel': // 取消事件
        stateMgr.mouseUp(p)
        break;
      case 'pointerout': // 鼠标移出元素
        stateMgr.mouseUp(p)
        break;
    }
  },



  wheel(p: WheelEventInfo) {

    stateMgr.wheel(p);
  }
}


export default receiver;

